#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include "Partitions.h"
#include "SuffixTree.h"

#define MAX_PATH_LENGTH 200
#define OUTPUT_BUFFER 7680000   //7500*1024
#define TAIL_OVERLAP 1000
#define debug 1

int totalWrittenInSuffixArray=0;
Suffix *suffixBuffer;
int outputBufferSize;

int maxSuffixArraylength;

void buildAndOutputSortedList(int *p,FILE *inputFile,FILE *binaryinputFile, FILE *outputFile, 
							 int binaryInputlength, int outputlength, int *inputAsInt,
							 unsigned int *binaryinputBuffer, int fileNumber)
{

	int chunklength;
	int result;
	int binarychunk;
	int writtensuffixes;

	fseek (inputFile , 0 , SEEK_END);
	
	chunklength=(ftell (inputFile))/sizeof(int);
	rewind(inputFile);

	result = fread (inputAsInt,sizeof(int),chunklength,inputFile);

	if (result != chunklength) 
	{
	  printf ("Reading DNA error 2\n");
	  exit (2);
	}
	
	
	fseek (binaryinputFile , 0 , SEEK_END);
	binarychunk=(ftell (binaryinputFile))/sizeof(unsigned int);//chunklength*2/(numBitsInLong)+1;
	rewind(binaryinputFile);
	result = fread (binaryinputBuffer,sizeof(unsigned int),binarychunk,binaryinputFile);


	if (result != binarychunk) 
	{
	  printf ("Reading binary DNA error 2\n");
	  exit (2);
	}
	

	writtensuffixes=buildSuffixArrayLarsson(p,inputAsInt,binaryinputBuffer,chunklength,
		binarychunk, outputlength,outputFile,fileNumber);
	
	if(totalWrittenInSuffixArray+writtensuffixes>=2000000000)
	{
		printf("written %d suffices\n",totalWrittenInSuffixArray);
		totalWrittenInSuffixArray=writtensuffixes;
	}

	totalWrittenInSuffixArray+=writtensuffixes;	
}


int sortPartitions(char *smallBinaryFileNamePrefix, char *smallNumericFileNamePrefix,
							char *lengthsFileName, char *fileNumbersFileName, char *binarylengthsFileName,
							char *smallSuffixArrayFileNamePrefix)
{
	FILE *smallOutputFile;
	FILE *smallNumericFile;
	FILE *smallBinaryFile;
	int i;
	
	int *inputBuffer;
	unsigned int *inputbinaryBuffer;
	int *p; //temp for Larsson


	char currnumericfilename [MAX_PATH_LENGTH];
	char currbinaryfilename [MAX_PATH_LENGTH];
	char currsarrayfilename [MAX_PATH_LENGTH];

	//1. Get information about input partitions
	int numOfChunks=getNumberOfChunks(fileNumbersFileName);


	int *lengths=(int*) calloc (numOfChunks, sizeof(int)); 
	int *binarylengths=(int*) calloc (numOfChunks, sizeof(int)); 
	int *filenumbers=(int*) calloc (numOfChunks, sizeof(int));

	

	readPartitionInfo(lengthsFileName,fileNumbersFileName,binarylengthsFileName,
					   lengths, filenumbers,binarylengths,numOfChunks);



	//2. allocate memory for suffix array buffer
	outputBufferSize=MIN(OUTPUT_BUFFER,lengths[0]);	

	suffixBuffer=(Suffix *) malloc(outputBufferSize* sizeof(Suffix) );
	if(suffixBuffer==NULL)
	{
		printf("Could not allocate memory for suffix buffer of size %d suffices\n",outputBufferSize);
		return 1;
	}

	//3.//allocate memory for input arrays - suppose that the first chunk is the biggest 
	
	//maxSuffixArraylength=lengths[0]+TAIL_OVERLAP+1;
		
	inputBuffer=(int*) calloc (maxSuffixArraylength, sizeof(int));
	inputbinaryBuffer=(unsigned int*) calloc ((maxSuffixArraylength*2)/32+2, sizeof(unsigned int));
	p=(int *)malloc((maxSuffixArraylength+1)*sizeof *p);

	//4.sort suffices in each file and output small suffix arrays
	for(i=0;i<numOfChunks;i++)  
	{		
		int outputSize=lengths[i];
		int binaryInputsize=binarylengths[i];
		sprintf(currnumericfilename,"%s_%i", smallNumericFileNamePrefix,i);
		sprintf(currbinaryfilename,"%s_%i", smallBinaryFileNamePrefix,i);
		sprintf(currsarrayfilename,"%s_%i", smallSuffixArrayFileNamePrefix,i);

		
		smallNumericFile = fopen(currnumericfilename, "rb");
		if(smallNumericFile==NULL) 
		{
			printf("Error: can't open file number %i of numeric encoded DNA.\n",i);
			return 2;
		}

		smallBinaryFile = fopen(currbinaryfilename, "rb");
		if(smallBinaryFile==NULL) 
		{
			printf("Error: can't open file number %i of binary encoded DNA.\n",i);
			return 2;
		}	

		
		if(!(smallOutputFile= fopen ( currsarrayfilename , "wb" )))
		{
			printf("Could not open suffix array file \"%s\" for output \n", currsarrayfilename);
			return 1;
		}
	
		buildAndOutputSortedList(p,smallNumericFile,smallBinaryFile,smallOutputFile,binaryInputsize, 
								outputSize,inputBuffer,inputbinaryBuffer,i);	
	
		fclose(smallNumericFile);
		fclose(smallBinaryFile);
		fclose(smallOutputFile);
		printf("processed partition %i out of %i\n",i,numOfChunks);		
	}
	
	return 0;
}

/*int main(int argc, char *argv[])
{
	FILE *file;
	int i;
	unsigned int* inputbinaryBuffer=(unsigned int*) calloc (10, sizeof(unsigned int));

	file=fopen("C:\\inputs\\flaviviridae\\temp\\flavi_smallbinary_0","rb");
	fread(inputbinaryBuffer,sizeof(unsigned int),10,file);
	for(i=0;i<10;i++)
		printBitSequence(&inputbinaryBuffer[i]);

}*/

int main(int argc, char *argv[])
{	
	char inputfilename [MAX_PATH_LENGTH];	
	char smallNumericFileNamePrefix[MAX_PATH_LENGTH];
	char smallBinaryFileNamePrefix[MAX_PATH_LENGTH];
	char lengthsFileName[MAX_PATH_LENGTH];
	char fileNumbersFileName[MAX_PATH_LENGTH];
	char smallSuffixArrayFileNamePrefix[MAX_PATH_LENGTH];
	char bitSequencesLengthsFileName[MAX_PATH_LENGTH];
	clock_t startclock, stopclock;
	FILE *infofile;
	char infofilename[MAX_PATH_LENGTH];
	int info[3];

	if(argc<4)
	{
		printf("sortPartitions <inputfilefolder> <tempfilefolder> <inputfileprefix>\n");
		return 1;
	}

	

	sprintf(inputfilename,"%s%s", argv[2], argv[3]);	
	sprintf(smallNumericFileNamePrefix,"%s_smallnumeric", inputfilename);
	sprintf(smallBinaryFileNamePrefix,"%s_smallbinary", inputfilename);
	sprintf(lengthsFileName,"%s_lengths", inputfilename);
	sprintf(fileNumbersFileName,"%s_filenumbers", inputfilename);
	sprintf(smallSuffixArrayFileNamePrefix,"%s_small_sarray", inputfilename);	
	sprintf(bitSequencesLengthsFileName,"%s_binarylengths", inputfilename);
	
	sprintf(infofilename,"%s%s_input_info", argv[1],argv[3]);
	//1. read info to compute min substript,max subscript and maxfile size
	if(!(infofile= fopen ( infofilename , "rb" )))
	{
		printf("Could not open input info file %s for reading \n",infofilename);
		return 1;
	}
	
	
	
	if(fread(info, sizeof(int), 3, infofile)!=3)
	{
		printf("Error reading input info \n");
		return 1;
	}
	fclose(infofile);
	
	maxSuffixArraylength=info[2];
	
	startclock = clock();

	if(sortPartitions(smallBinaryFileNamePrefix,smallNumericFileNamePrefix,
							lengthsFileName, fileNumbersFileName,bitSequencesLengthsFileName, 
							smallSuffixArrayFileNamePrefix))
		return 1;

	stopclock = clock();
	
	printf("%f mseconds total\n", (double) (stopclock-startclock));
	printf("written in total %d suffices\n",totalWrittenInSuffixArray);
	
	return 0;
}
